using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Reflection;
using Developex.DatabaseWrapper;
using Developex.DatabaseWrapper.Fields;
using Developex.DatabaseWrapper.Attributes;

namespace DataLayer.Objects
{
   /// <summary>
   /// 
   /// </summary>
   public enum SiteUser_Fields
   {
      #region Mapped Fields

		Id,
		Name,
		Age,

      #endregion
   }

   /// <summary>
   /// 
   /// </summary>
   public class SiteUser : Row
   {
      #region Custom Init

      private void CustomInit()
      {
         // make initialization like custom fields adding
      }

      protected virtual IField CreateCustomField(SiteUser_Fields propertyName)
      {
         // create custom field by field name
         return null;
      }

      private IField CreateCustomField(string propertyName)
      {
         // create custom field by field name
         return CreateCustomField((SiteUser_Fields)Enum.Parse(typeof(SiteUser_Fields), propertyName, true));
      }

      #endregion

      #region Constructors

		static public readonly SiteUser SampleItem = new SiteUser();

		protected override Row GetSampleItem()
		{
			return SampleItem;
		}

		/// <summary>
		/// Default Constructor
		/// </summary>
		public SiteUser()
			: this(true, true)
		{
		}

		/// <summary>
		/// Constructor
		/// </summary>
		/// <param name="createFields"></param>
		/// <param name="customInit"></param>
		public SiteUser(bool createFields, bool customInit)
			: base("Users")
		{
			if (createFields)
				AddGeneratedFields();
			if (customInit)
				CustomInit();
		}

		/// <summary>
		/// Constructor, with custom table name
		/// </summary>
		/// <param name="tableName">Table name</param>
		public SiteUser(string tableName)
			: base(tableName)
		{
			AddGeneratedFields();
			CustomInit();
		}

		/// <summary>
		/// Create only given field
		/// </summary>
		/// <param name="fieldsToCreate">Fields to create</param>
		public SiteUser(params Enum[] fieldsToCreate)
			: this("Users", fieldsToCreate)
		{
		}

		/// <summary>
		/// Create only given field, with custom table name
		/// </summary>
		/// <param name="tableName">Table name</param>
		/// <param name="fieldsToCreate">Fields to create</param>
		public SiteUser(string tableName, params Enum[] fieldsToCreate)
			: base(tableName)
		{
			if (fieldsToCreate.Length == 0)
			{
				AddGeneratedFields();
				CustomInit();
				return;
			}
			foreach (Enum fieldToCreate in fieldsToCreate)
			{
				CreateAndAddField(fieldToCreate);
			}
		}

		#region Fields Creation

		/// <summary>
		/// Create object for clone
		/// </summary>
		/// <returns/>
		/// <remarks>
		/// NB!: don't add any fields here
		///              Here should be only object creation, all data copy should be in overrided Clone function.
		///              Used only in base version of Clone function.
		///              Should be overrided for ICloneable interface.
		/// </remarks>
		protected override Row CreateObjectForClone()
		{
			return new SiteUser(false, false);
		}

		protected internal void AddGeneratedFields()
		{
			id = new IntPrimaryKey("id");
			AddField(id);
			name = new StringField("name", FieldFlags.DisableNull, NameMaxLength);
			AddField(name);
			age = new Field<int?>("age");
			AddField(age);
		}

		/// <summary>
		/// Add field by it's enum
		/// </summary>
		/// <param name="propertyName"></param>
		public override void CreateAndAddField(Enum propertyName)
		{
			CreateAndAddField(propertyName.ToString());
		}

		/// <summary>
		/// Create and add field by mapped property name
		/// </summary>
		/// <param name="propertyName"></param>
		public override void CreateAndAddField(string propertyName)
		{
			IField fieldToAdd = null;
			switch (propertyName)
			{
				case "Id":
					fieldToAdd = id = new IntPrimaryKey("id");
					break;
				case "Name":
					fieldToAdd = name = new StringField("name", FieldFlags.DisableNull, NameMaxLength);
					break;
				case "Age":
					fieldToAdd = age = new Field<int?>("age");
					break;
			}
			if (fieldToAdd == null)
				fieldToAdd = CreateCustomField(propertyName);
			if (fieldToAdd == null)
				throw new InvalidOperationException("Cannot find field with mapped property = " + propertyName);
			AddField(fieldToAdd);
		}

		#endregion

      #endregion

      #region MaxLength

		/// <summary>
		/// Max Length for property Name
		/// </summary>
		public static readonly int NameMaxLength = 50;

      #endregion

      #region Fields

		/// <summary>
		/// </summary>
		[PropertyName("Id")]
		protected internal IntPrimaryKey id = null;

		/// <summary>
		/// </summary>
		[PropertyName("Name")]
		protected internal StringField name = null;

		/// <summary>
		/// </summary>
		[PropertyName("Age")]
		protected internal Field<int?> age = null;

      #endregion

      #region Properties

		/// <summary>
		/// 
		/// </summary>
		public int Id
		{
			get { return id; }
			set { id.Value = value; }
		}

		/// <summary>
		/// </summary>
		public IntPrimaryKey _Id
		{
			get { return id; }
		}

		/// <summary>
		/// 
		/// </summary>
		public string Name
		{
			get { return name; }
			set { name.Value = value; }
		}

		/// <summary>
		/// </summary>
		public StringField _Name
		{
			get { return name; }
		}

		/// <summary>
		/// 
		/// </summary>
		public int? Age
		{
			get { return age; }
			set { age.Value = value; }
		}

		/// <summary>
		/// </summary>
		public Field<int?> _Age
		{
			get { return age; }
		}

      #endregion
   }
}
